package com.labot.webapp.action;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.labot.dao.SearchException;
import com.labot.dto.I18nDto;
import com.labot.dto.mapper.I18nMapper;
import com.labot.exceptions.ExceptionDomain;
import com.labot.i18n.CustomListResourceBundle;
import com.labot.model.I18n;
import com.labot.types.AuditType;
import com.labot.util.FilePropertiesUtils;
import com.labot.util.StackTraceUtils;
import com.labot.webapp.action.messages.TextMessagesType;

/**
 * Action for facilitating User Management feature.
 */
public class ResourceBundleAction extends BaseAction {
    private static final long serialVersionUID = 6776548938712115191L;
    //Pagina
    private String page; //Valores posibles " list, empty, listTextMessageTypeKeys "
    //Valores para el listado
    private List<I18nDto> keys;
    private String query;
    //Valores de Edicion
    private HashMap<String, String> valoresCargados;
    private HashMap<String, String> valoresCargados_es;
    //Valores de altas
    private HashMap<String, String> valoresNuevos_key;
    private HashMap<String, String> valoresNuevos;
    private HashMap<String, String> valoresNuevos_es;
    //Valores de Borrado
    private HashMap<String, String> valoresSeleccionados;
    //Upload Files Properties
    private File file;
    private String fileContentType;
    private String fileFileName;
    private File file_es;
    private String fileContentType_es;
    private String fileFileName_es;
    private Boolean overwrite;

    /**
     * Default: just returns "success"
     *
     * @return "success"
     */
    public String execute() {
        return SUCCESS;
    }
    
    public String cancel() {
    	return CANCEL;
    }
    
    /**
     * Carga archivos de Properties para i18n
     * @return
     * @throws Exception
     */
    public String uploadFiles() throws Exception {
        //retrieve the file data
    	Map<String, String> resources    = FilePropertiesUtils.getProperties(file);    	
    	Map<String, String> resources_es = FilePropertiesUtils.getProperties(file_es);
    	savePropertiesFile(resources, resources_es);
    	CustomListResourceBundle.reloadBoundles();
    	return SUCCESS;
    }
    
    /**
     * Carga los archivos en los bundles
     * @param resources
     * @param resources_es
     */
    private void savePropertiesFile( Map<String, String> resources, Map<String, String> resources_es ) {
    	//Sumar las keys
    	Set<String> keys = new HashSet<String>(resources.keySet());
    	keys.addAll( new HashSet<String>(resources_es.keySet()) );
    	
    	super.log(AuditType.INFO, "Upload i18n file. Begining process...");
		
    	//iterar y procesar, hay algunas que quedar�n en NULL
    	for (String key : keys) {
    		String value    = resources.get(key);
    		String value_es = resources_es.get(key);
    		try {
    			I18n i18n = i18nManager.getI18n(key);
    			if(i18n != null) {
    				if(overwrite) {    					
    					i18n.setEn(value);
    					i18n.setEs(value_es);
    					i18nManager.save(i18n);
    					super.log(AuditType.INFO, "Existing key, overwriting: " + i18n.getKey());
    				}
    			} else {
    				i18n = new I18n(key);
    				i18n.setEn(value);
    				i18n.setEs(value_es);
    				i18nManager.save(i18n);
					super.log(AuditType.INFO, "New key: " + i18n.getKey());
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
		}
    	super.log(AuditType.INFO, "Upload i18n file. Finishing process...");
    }
    

    /**
     * Metodo que graba todas las nuevas de cualquier origen y edita existentes
     * @return
     */
    public String saveAll() {
    	
    	String mensaje = super.getText(TextMessagesType.RESOURCEBUNDLEACTION_SAVETITLE.getKey()); //"Se han modificado los siguientes Resources: ";
    	Boolean modificaciones = false;
    	
    	//Edicion de valores Keys
    	if(valoresCargados != null) {    		
    		Iterator<?> it = valoresCargados.entrySet().iterator();
    		while (it.hasNext()) {
    			@SuppressWarnings("unchecked")
    			Map.Entry<String, String> pairs = (Map.Entry<String, String>)it.next();
    			
    			try {
    				String newValue = valoresCargados.get(pairs.getKey());
    				String newValue_es = valoresCargados_es.get(pairs.getKey());
    				if(newValue.length() >= 1024){
    					throw new ExceptionDomain("Data too long!");
    				}
    				if(newValue_es.length() >= 1024){
    					throw new ExceptionDomain("Data too long!");
    				}
    				I18n i18n = i18nManager.get(Long.parseLong(pairs.getKey()));
    				String oldValue = i18n.getEn();
    				String oldValue_es = i18n.getEs();
    				if (!(newValue.equals(oldValue)) || !(newValue_es.equals(oldValue_es))) {
    					i18n.setEn(newValue);
    					i18n.setEs(newValue_es);
    					i18nManager.save(i18n);
//					i18nManager.modifyKey(i18n.getId(), newValue, newValue_es);
    					log.info("Se ha modificado la Config: " + i18n.getKey() + " - valor viejo: " + oldValue + " - valor nuevo: " + newValue);
    					log.info("Se ha modificado la Config: " + i18n.getKey() + " - valor viejo: " + oldValue_es + " - valor nuevo: " + newValue_es);
    					mensaje = mensaje.concat(i18n.getKey() + ", ");
    					modificaciones = true;
    					super.log(AuditType.INFO, "Editing i18n key: " + i18n.getKey() + " - EN: " + oldValue + " -> " + newValue + " - ES: " + oldValue_es + " -> " + newValue_es);
    				}
    			} catch (Exception e) {
    				saveExceptionMessage(super.getText(TextMessagesType.RESOURCEBUNDLEACTION_SAVE.getKey()) + " " + pairs.getKey() + " - " + e.getMessage());//"ERROR al grabar el Resource: " + pairs.getKey());
    			}
//            saveMessage("Se ha grabado correctamente.");
    		}
    	}
        //Altas
        if (valoresNuevos_key != null) {        	
        	Iterator<?> itAlta = valoresNuevos_key.entrySet().iterator();
        	while (itAlta.hasNext()) {
        		@SuppressWarnings("unchecked")
				Map.Entry<String, String> pairs = (Map.Entry<String, String>)itAlta.next();
        		try {
        			if (!valoresNuevos_key.get(pairs.getKey()).trim().equals("")) {        				
        				if( !( valoresNuevos.get(pairs.getKey()).trim().equals("")) 
        						|| !(valoresNuevos_es.get(pairs.getKey()).trim().equals("") )) {
        					
        					I18n i18n = null;
        					i18n = i18nManager.getI18n(valoresNuevos_key.get(pairs.getKey()).trim());
        					if(i18n != null) {
        						throw new Exception("Duplicated!");
        					}
        					if(valoresNuevos_key.get(pairs.getKey()).trim().length() >= 255){
            					throw new ExceptionDomain("Data too long!");
            				}
        					if(valoresNuevos.get(pairs.getKey()).length() >= 1024){
            					throw new ExceptionDomain("Data too long!");
            				}
            				if(valoresNuevos_es.get(pairs.getKey()).length() >= 1024){
            					throw new ExceptionDomain("Data too long!");
            				}
        					i18n = new I18n(valoresNuevos_key.get(pairs.getKey()).trim());
        					i18n.setEn(valoresNuevos.get(pairs.getKey()));
        					i18n.setEs(valoresNuevos_es.get(pairs.getKey()));
        					i18nManager.save(i18n);
        					mensaje = mensaje.concat(i18n.getKey() + ", ");
        					modificaciones = true;
        					super.log(AuditType.INFO, "New i18n key: " + i18n.getKey() + " - EN: " + i18n.getEn() + " / ES: " + i18n.getEs());
        				}
        			}
        		} catch (Exception e) {
        			saveExceptionMessage(super.getText(TextMessagesType.RESOURCEBUNDLEACTION_ERROR_CREATE.getKey()) + pairs.getKey() + " - " + e.getMessage());//"ERROR: al dar de alta el Resource: " + pairs.getKey());
        		}
        	}
        }
        
    	if (modificaciones) {    	
    		mensaje = mensaje.substring(0, mensaje.length()-2);
    		saveMessage(mensaje);
    		CustomListResourceBundle.reloadBoundles();
//    		try {    		
//    			StartupListener.loadConfig(getSession().getServletContext());
//    		} catch (Exception e) {
//    			String error = "ERROR al recargar las Configs en el Sistema, reinicie la aplicaci&oacte;n para reflejar los cambios.";
//    			addActionError(error);
//    			log.error(error);
//    		}
    	} else {
    		if(!super.hasActionException()) {    			
    			saveMessage(super.getText(TextMessagesType.RESOURCEBUNDLEACTION_NO_MODIFICATIONS.getKey()));//"No se encontraron modificiones para realizar.");
    		}
    	}
    	
    	
    	return SUCCESS;
    }
    
    /**
     * Hace un recorrido por todas las JSP y devuelve una lista de todas las
     * key que faltan incorporar al bundle
     * @return
     */
    public String empty() { 
    	page = "empty";
    	String path = getSession().getServletContext().getRealPath("WEB-INF");
    	keys = i18nManager.getJspKeys(path, true);
    	Long i = 1L;
    	for (I18nDto dto : keys) {
			dto.setId(i);
			i++;
		}
    	return SUCCESS;
    }
    
    /**
     * Borra keys del bundle
     * @return
     */
    public String delete() {
    	Boolean modificaciones = false;
    	String mensaje = super.getText(TextMessagesType.RESOURCEBUNDLEACTION_DELETE.getKey()); //"Se han modificado los siguientes Resources: ";
    	if (valoresSeleccionados != null) {
    		Iterator<?> itAlta = valoresSeleccionados.entrySet().iterator();
        	while (itAlta.hasNext()) {
        		@SuppressWarnings("unchecked")
				Map.Entry<String, String> pairs = (Map.Entry<String, String>)itAlta.next();
        		try {        			
        			if(pairs.getValue().toLowerCase().contains("on")) {
        				I18n i18n = i18nManager.get(Long.parseLong(pairs.getKey()));
        				super.log(AuditType.INFO, "Deleted i18n key: " + i18n.getKey() + " - EN: " + i18n.getEn() + " / ES: " + i18n.getEs());
        				i18nManager.remove(i18n);
        				mensaje = mensaje.concat(i18n.getKey() + ", "); 
        				modificaciones = true;
        			}
        		} catch (Exception e) {
        			addActionException(StackTraceUtils.getStackTrace(e));
        		}
        	}
    	}
    	if (modificaciones) {    	
    		mensaje = mensaje.substring(0, mensaje.length()-2);
    		addActionMessage(mensaje);
    		CustomListResourceBundle.reloadBoundles();
    	} else {
    		if(!super.hasActionException()) {    			
    			addActionWarning(super.getText(TextMessagesType.RESOURCEBUNDLEACTION_NO_MODIFICATIONS.getKey()));//"No se encontraron modificiones para realizar.");
    		}
    	}
    	return SUCCESS;
    }


    /**
     * Lista keys del bundle db
     * @return
     */
    public String list() {
    	page = "list";
        try {
        	keys = I18nMapper.mapModelListToDtoList(i18nManager.search(query, I18n.class));
        } catch (SearchException se) {
        	keys = I18nMapper.mapModelListToDtoList(i18nManager.getAll());
        }
        return SUCCESS;
    }
    
    /**
     * Lista keys de mensajes de actions recorriendo TextMessageType
     * @param q
     */
    public String listTextMessageTypeKeys() {
    	page = "listTextMessageTypeKeys";
    	keys = new ArrayList<I18nDto>();
    	Set<I18nDto> set = new HashSet<I18nDto>();
    	Long count = 1L;
    	for (TextMessagesType msg : TextMessagesType.values()) {
    		I18n model = i18nManager.getI18n(msg.getKey());
    		I18nDto dto = new I18nDto();  
			if (model != null) {
				dto = I18nMapper.mapModelToDto(model);
				dto.setExist(true);
			} else {
				dto = new I18nDto();
				dto.setId(count);
				dto.setKey(msg.getKey());
				dto.setExist(false);
				count++;
			}
			dto.setPage(msg.toString());
			set.add(dto);
		}
    	keys.addAll(set);
    	return SUCCESS;
    }
    
    public void setQ(String q) {
        this.query = q;
    }

	public List<I18nDto> getKeys() {
		return keys;
	}
	
	public void setKeys(List<I18nDto> keys) {
		this.keys = keys;
	}

	public HashMap<String, String> getValoresCargados() {
		return valoresCargados;
	}

	public void setValoresCargados(HashMap<String, String> valoresCargados) {
		this.valoresCargados = valoresCargados;
	}

	public HashMap<String, String> getValoresCargados_es() {
		return valoresCargados_es;
	}

	public void setValoresCargados_es(HashMap<String, String> valoresCargados_es) {
		this.valoresCargados_es = valoresCargados_es;
	}

	public HashMap<String, String> getValoresNuevos_key() {
		return valoresNuevos_key;
	}

	public void setValoresNuevos_key(HashMap<String, String> valoresNuevos_key) {
		this.valoresNuevos_key = valoresNuevos_key;
	}

	public HashMap<String, String> getValoresNuevos() {
		return valoresNuevos;
	}

	public void setValoresNuevos(HashMap<String, String> valoresNuevos) {
		this.valoresNuevos = valoresNuevos;
	}

	public HashMap<String, String> getValoresNuevos_es() {
		return valoresNuevos_es;
	}

	public void setValoresNuevos_es(HashMap<String, String> valoresNuevos_es) {
		this.valoresNuevos_es = valoresNuevos_es;
	}

	public File getFile() {
		return file;
	}

	public void setFile(File file) {
		this.file = file;
	}

	public String getFileContentType() {
		return fileContentType;
	}

	public void setFileContentType(String fileContentType) {
		this.fileContentType = fileContentType;
	}

	public String getFileFileName() {
		return fileFileName;
	}

	public void setFileFileName(String fileFileName) {
		this.fileFileName = fileFileName;
	}

	public File getFile_es() {
		return file_es;
	}

	public void setFile_es(File file_es) {
		this.file_es = file_es;
	}

	public String getFileContentType_es() {
		return fileContentType_es;
	}

	public void setFileContentType_es(String fileContentType_es) {
		this.fileContentType_es = fileContentType_es;
	}

	public String getFileFileName_es() {
		return fileFileName_es;
	}

	public void setFileFileName_es(String fileFileName_es) {
		this.fileFileName_es = fileFileName_es;
	}

	public Boolean getOverwrite() {
		return overwrite;
	}

	public void setOverwrite(Boolean overwrite) {
		this.overwrite = overwrite;
	}

	public HashMap<String, String> getValoresSeleccionados() {
		return valoresSeleccionados;
	}

	public void setValoresSeleccionados(HashMap<String, String> valoresSeleccionados) {
		this.valoresSeleccionados = valoresSeleccionados;
	}

	public String getPage() {
		return page;
	}

	

}
